/**
 * Created by Ahmed Medhat & Sweelam on 8/2/2015.
 */


//Default Appending TAG
var appending_area='#g';

/* Create obj that hold container.
 Set the svg container and make its attributes as default
 */
var Main_Bound_region = {

    body:d3.select("body"),
    id_Main_Bound_region :0,
    id_Group_Bound_region :0,
    svg_width: 800,
    svg_height: 800,
    g_width: 200,
    g_height: 200,

    //Append SVG
    SVG: function(){
        var Container = this.body
            .append("svg")
            .attr("width", this.svg_width)
            .attr("height", this.svg_height)
            .attr("id","svg"+this.id_Main_Bound_region);
        this.id_Main_Bound_region++;
        return Container;
    },

    //Append G
    G: function (append) {

        if(append == 'svg'|| append== 'SVG')
            append= '#svg'+(this.id_Main_Bound_region-1);
        else if(append == 'body')
            append= 'body';
        else
            append= '#'+append;


        var GContainer = d3.select(append)
            .append("g")
            .attr("width", this.g_width)
            .attr("height", this.g_height)
            .attr("id","g"+this.id_Group_Bound_region);
        this.id_Group_Bound_region++;
        return GContainer;

    }
};


/* The object that holds all geometry primitives */
var Geo_Primitives = {

    /**
     *  Description
     * @ method : Draw_Axis
     * @ inputs :(Object of Data set , Col Header ) OR ( Minimum Domain , Maximum Domain)  , Minimum Range , Maximum Range ,(Type) Vertical || Horizontal and Number of Ticks , Group ID.
     * @ retuen : Non
     * */
    Draw_Axis: function(Dataset,col_name,max_domain,min_domain,max_range,min_range,type,no_ticks,where_append){
        var c;
        var app= '#g'+where_append;
        if(type=="H" || type=="h") {
            c=this.Scale(Dataset,col_name,max_domain,min_domain,max_range,min_range,'x');
            var axis_coordinate = d3.svg.axis().ticks(no_ticks).orient("bottom").scale(c);

            return d3.select(app).append("g").call(axis_coordinate);


        }
        if(type=="V" || type=="v")
        {
            c=this.Scale(Dataset,col_name,max_domain,min_domain,max_range,min_range,'y');
            var axis_coordinate = d3.svg.axis().ticks(no_ticks).orient("left").scale(c);

            return d3.select(app).append("g").call(axis_coordinate);
        }

    },


    /**
     *  Description
     * @ method : Draw Line
     * @ inputs : Coordinates, Stroke color and group id.
     * @ retuen : Non
     * */
    DrawLine : function(x1, y1, x2, y2,stroke,stroke_width ,where_append)
    {
        /* Default Var*/
        where_append            =  appending_area+where_append;
        x1           = x1||0;
        y1           = y1||0;
        x2           = x2||0;
        y2           = y2||0;
        stroke       =stroke||"black";
        stroke_width =stroke_width||1;

        /* Shape D3 Drawer*/
        var line = d3.select( where_append).append("line")
            .attr("x1", x1)
            .attr("y1", y1)
            .attr("x2", x2)
            .attr("y2", y2)
            .attr("stroke",stroke)
            .attr("stroke-width",stroke_width);
        return line;
    },


    /**
     *  Description
     * @ method : Draw Rectangle
     * @ inputs : Coordinates, width, height, corners rotate, body color, Stroke color, opcity degree and group id.
     * @ retuen : Non
     * */
    DrawRect: function(x, y, width, height,rx, ry ,fill,stroke,stroke_width,fill_opacity,where_append)
    {

        /* Default Var*/
        where_append            =  appending_area+where_append;
        x             = x||0;
        y             = y||0;
        rx            =rx||0;
        ry            =ry||0;
        width         =width||5;
        height        =height||5;
        stroke        =stroke||"black";
        stroke_width  =stroke_width||1
        fill          =fill || "white";
        fill_opacity       =fill_opacity || 1;

        /* Shape D3 Drawer*/
        var rect = d3.select(where_append).append("rect")
            .attr("x", x)
            .attr("y", y)
            .attr("width", width )
            .attr("height", height )
            .attr("fill", fill)
            .attr("rx",rx)
            .attr("ry",ry)
            .attr("stroke",stroke)
            .attr("stroke-width",stroke_width)
            .attr("fill-opacity",fill_opacity);
        return rect;
    },


    /**
     *  Description
     * @ method : Draw circle
     * @ inputs : Coordinates, radius, Stroke color, body color and group id.
     * @ retuen : Non
     * */
    DrawCircle: function(Dataset,cx,cy,r,stroke,stroke_width,fill,where_append) {


        /* Default Var*/
        where_append = appending_area + where_append;
        cx = cx || 0;
        cy = cy || 0;
        r = r || 2;
        stroke = stroke || "black";
        stroke_width = stroke_width || 1;
        fill = fill || "black";

        var width=d3.select(where_append).attr("width");
        var height=d3.select(where_append).attr("height");
        var scalex=this.Scale(Dataset,cx,0,0,width-10,20,'x');
        var scaley=this.Scale(Dataset,cy,0,0,height-10,20,'y');


        /* Shape D3 Drawer*/
        if (Dataset == null) {

            return d3.select(where_append).append("circle")
            .attr("cx", cx)
            .attr("cy", cy)
            .attr("r", r)
            .attr("stroke", stroke)
            .attr("stroke-width", stroke_width)
            .attr("fill", fill);
        }
        else
        {
            return d3.select(where_append).selectAll("circle")
                .data(Dataset)
                .enter()
                .append("circle")
                .attr("cx",function (d){return scalex(d[cx])})		// Here.
                .attr("cy",function (d){return scaley(d[cy])})		// Here.
                .attr("r", r)
                .attr("stroke", stroke)
                .attr("stroke-width", stroke_width)
                .attr("fill", fill)
             ;

        }

    },


    /**
     *  Description
     * @ method : Draw Ellipse
     * @ inputs : Coordinates, radiuses, Stroke color, body color and group id.
     * @ retuen : Non
     * */
    DrawEllipse: function(cx, cy, rx, ry,fill,where_append)
    {
        /* Default Var*/
        where_append            =  appending_area+where_append;
        cx           =cx||0;
        cy           =cy||0;
        rx            =ry||100;
        ry            =ry||10;
        fill         =fill || "black";

        /* Shape D3 Drawer*/
        var ellipse = d3.select(where_append).append("ellipse")
            .attr("cx", cx)
            .attr("cy", cy)
            .attr("rx", rx)
            .attr("ry", ry)
            .attr("fill", fill);
        return ellipse;
    },


    /**
     *  Description
     * @ method : Draw Polygon
     * @ inputs : Array of Points , Body Color , Stroke Color , Stroke Width ,(Fill Rule) evenodd || nonzero and group id.
     * @ retuen : Non
     * */
    DrawPolygon: function(points,fill,stroke,stroke_width,fill_rule,where_append)
    {

        /* Default Var*/
        where_append            =  appending_area+where_append;
        points           =points||"100,10 40,198 100,10 40,198 100,10 40,198";
        fill         =fill || "black";
        stroke         =stroke || "black";
        stroke_width         =stroke_width || 1;
        fill_rule         =fill_rule || "nonzero";


        /* Shape D3 Drawer*/
        var polygon= d3.select(where_append).append("polygon")
            .attr("points",points)
            .attr("fill",fill)
            .attr("stroke",stroke)
            .attr("stroke-width",stroke_width)
            .attr("fill-rule",fill_rule);
        return polygon;
    },


    /**
     *  Description
     * @ method : Draw_Axis
     * @ inputs : Array of Points , Body Color , Stroke Color , Stroke Width and group id.
     * @ retuen : Non
     * */
    DrawPolyline: function(points,fill,stroke,stroke_width,where_append)
    {

        /* Default Var*/
        where_append            =  appending_area+where_append;
        points           =points||"100,10 40,198 100,10 40,198 100,10 40,198";
        fill         =fill || "white";
        stroke         =stroke || "black";
        stroke_width         =stroke_width || 1;


        /* Shape D3 Drawer*/
        var polyLine = d3.select(where_append).append("polyline")
            .attr("points",points)
            .attr("fill",fill)
            .attr("stroke",stroke)
            .attr("stroke-width",stroke_width);
        return polyLine;
    },
	
	Color: function(Category_id){

        var color;
        if(Category_id !=null) {
            if (Category_id == '10')
                return d3.scale.category10();
            else if(Category_id=='20b')
                return d3.scale.category20b();
            else if(Category_id=='20c')
                return d3.scale.category20c();
            else if(Category_id=='20')
                return d3.scale.category20();
            else
            console.log("No Color Category With this ID");
        }
    },
	
    /**
     *  Description
     * @ method : Scale
     * @ inputs : (Object of Data set , Col Header ) OR ( Minimum Domain , Maximum Domain) , Minimum Range , Maximum Range ,(axis) X || Y.
     * @ retuen : Non
     * */
    Scale: function(Dataset,col_name,max_domain,min_domain,max_range,min_range,axis)
    {

         if(axis=="x" || axis=="X"){

             if(Dataset == null && col_name==null){
                return d3.scale.linear()
                     .domain([dmin , dmax])
                     .range([min_range,max_range]);
             }
             else {
                 return d3.scale.linear()
                     .domain([d3.min(Dataset, function (d) {
                         return +d[col_name];
                     }), d3.max(Dataset, function (d) {
                         return +d[col_name];
                     })])
                     .range([min_range,max_range]);
             }

       }
        else if(axis=="y" || axis=="Y"){

             if(Dataset == null && col_name==null){

                 return d3.scale.linear()
                     .domain([dmin , dmax])
                     .range([max_range,min_range]);
             }
             else {
                 return d3.scale.linear()
                     .domain([d3.min(Dataset, function (d) {
                         return +d[col_name];
                     }), d3.max(Dataset, function (d) {
                         return +d[col_name];
                     })])
                     .range([max_range,min_range]);
             }

        }
        else
         {console.log("error occur in scale method")}

    }
};

